/* Copyright 2009 Requirement Management System
 * 
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.mags.exception.common;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 
 * @author Mario Gaitan
 *
 */
public class ExceptionHandlerImp extends AbstractExceptionHandler {
	private List<ExceptionKeyCreator> exceptionKeyCreators = null;
	private boolean ordered = false;
	private ExceptionMessageCreator messageCreator;
	
	@Override
	public boolean canHandle(Throwable exception) {
		if(exceptionKeyCreators!=null) {
			for(ExceptionKeyCreator i: exceptionKeyCreators) {
				if(i.canCreate(exception))
					return true;
			}
		}
		return false;
	}
	public ExceptionMessageCreator getMessageCreator() {
		return messageCreator;
	}
	public void setMessageCreator(ExceptionMessageCreator messageCreator) {
		this.messageCreator = messageCreator;
	}
	public void addExceptionKeyCreator(ExceptionKeyCreator keyCreator) {
		if(exceptionKeyCreators==null)
			exceptionKeyCreators = new ArrayList<ExceptionKeyCreator>();
		exceptionKeyCreators.add(keyCreator);
		ordered = false;
	}
	public List<ExceptionKeyCreator> getExceptionKeyCreators() {
		if(exceptionKeyCreators==null)
			addExceptionKeyCreator(new ExceptionKeyCreatorImp());
		return exceptionKeyCreators;
	}
	public List<ExceptionKeyCreator> getOrderedExceptionKeyCreators() {
		if(!ordered) {
			Collections.sort(getExceptionKeyCreators(), new Comparator<ExceptionKeyCreator>() {
				@Override
				public int compare(ExceptionKeyCreator creator1,
						ExceptionKeyCreator creator2) {
					double comparison = creator1.getOrder()-creator2.getOrder();
					if(comparison==0)
						return 0;
					else
						return comparison>0?1:-1;					
				}
				
			});
		}
		ordered = true;
		return getExceptionKeyCreators();
	}
	@Override
	public Collection<ExceptionDescriptor> getExceptionDescriptors(Throwable throwable)  {
		String key = getExceptionKey(throwable);
		ExceptionDescriptor descriptor = new ExceptionDescriptor(throwable, key);
		String resolvedKey = resolveKey(key);
		descriptor.setResolvedKey(resolvedKey);
		String message = getMessage(throwable, resolvedKey);
		descriptor.setMessage(message);
		String stackTrace = getStackTrace(throwable);
		descriptor.setStackTrace(stackTrace);
		List<ExceptionDescriptor> descriptors = new ArrayList<ExceptionDescriptor>();
		descriptors.add(descriptor);
		return descriptors;
	}
	protected String getExceptionKey(Throwable throwable) {
		for(ExceptionKeyCreator i: getOrderedExceptionKeyCreators())
			if(i.canCreate(throwable)) {
				String key = i.createKey(throwable);
				if(key!=null&&!key.equals(""))
					return key;
			}
		return "";
	}
	protected String resolveKey(String key) {
		if(messageCreator==null)
			 return key;
		else
			 return messageCreator.resolveKey(key);
	}
	protected String getMessage(Throwable throwable, String key) {
		String message = null;
		if(messageCreator==null)
			 message = key;
		else
			message = messageCreator.getMessage(key);
		message = appendExtraData(throwable, message);
		return message;
	}
}
